package com.ajieee.merge.service.impl;

import com.ajieee.merge.entity.finance.Quote;
import com.ajieee.merge.entity.finance.dto.BacktestResult;
import com.ajieee.merge.mapper.EtfQuoteMapper;
import com.ajieee.merge.service.BacktestService;
import com.ajieee.merge.service.QuoteService;
import com.ajieee.merge.util.TechIndicator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author ajieee
 * @date 2025-11-02
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BacktestServiceImpl implements BacktestService {

	private final QuoteService quoteService;

	private final EtfQuoteMapper etfQuoteMapper;

	@Override
	public List<BacktestResult> ma(String targetCode) {
		StopWatch sw = new StopWatch();
		sw.start();
		List<? extends Quote> quotes = quoteService.queryQuotesByTargetCode(targetCode);
		sw.stop();
		log.info("查询行情耗时：{}", sw.getTotalTimeMillis());

		StopWatch sw2 = new StopWatch();
		sw2.start();
		Map<LocalDate, BigDecimal> ma5 = TechIndicator.ma(quotes, 5);
		Map<LocalDate, BigDecimal> ma10 = TechIndicator.ma(quotes, 10);
		Map<LocalDate, BigDecimal> ma20 = TechIndicator.ma(quotes, 20);
		Map<LocalDate, BigDecimal> ma60 = TechIndicator.ma(quotes, 20);
		sw2.stop();
		log.info("计算MA耗时：{}", sw2.getTotalTimeMillis());

		StopWatch sw3 = new StopWatch();
		sw3.start();
		Map<LocalDate, BigDecimal> ema = TechIndicator.ema(quotes, 26);
		sw3.stop();
		log.info("计算EMA耗时：{}", sw3.getTotalTimeMillis());

		StopWatch sw4 = new StopWatch();
		sw4.start();
		Map<LocalDate, BigDecimal> macd = TechIndicator.macd(quotes, 12, 26, 9);
		sw4.stop();
		log.info("计算MACD耗时：{}", sw4.getTotalTimeMillis());

		List<String> dates = new ArrayList<>();
		List<Quote> goldenCrossDates = new ArrayList<>();
		List<Quote> deathCrossDates = new ArrayList<>();

		Quote buyInQuote = null;
		boolean isBullish = false;
		BigDecimal sumYield = BigDecimal.ZERO;
		for (int i = 0; i < quotes.size(); i++) {
			Quote quote = quotes.get(i);
			LocalDate curDate = quote.getDataDate();
//			if (curDate.isBefore(LocalDate.of(2022, 1, 1))
//					|| curDate.isAfter(LocalDate.of(2022, 12, 31))) {
//				continue;
//			}
//			if (curDate.isBefore(LocalDate.of(2025, 1, 1))) {
//				continue;
//			}

			if (ma5.get(curDate) == null || ma60.get(curDate) == null) {
				continue;
			}

			if (ma5.get(curDate).compareTo(ma60.get(curDate)) >= 0 && !isBullish) {
				// 金叉
				isBullish = true;
				goldenCrossDates.add(quote);

				dates.add(curDate + " - " + "金叉买入");
				// 第二天开盘价买入
				if (i + 1 < quotes.size() - 1) {
					buyInQuote = quotes.get(i + 1);
				}
			}

			if (ma5.get(curDate).compareTo(ma60.get(curDate)) <= 0 && isBullish) {
				// 5日均线下穿10日均线  死叉
				isBullish = false;
				deathCrossDates.add(quote);

				// 第二天开盘价卖出
				if (buyInQuote != null && i + 1 < quotes.size() - 1) {
					BigDecimal basePrice = BigDecimal.valueOf(buyInQuote.getOpen());
					BigDecimal profit = BigDecimal.valueOf(quotes.get(i + 1).getOpen()).subtract(basePrice);
					BigDecimal yield = profit.divide(basePrice, 8, RoundingMode.HALF_UP);
					sumYield = sumYield.add(yield);
					dates.add(curDate + " - " + "死叉卖出" + " - " + yield.multiply(BigDecimal.valueOf(100)));
				}
			}
		}

		BigDecimal finalProfit = BigDecimal.valueOf(10000).multiply(sumYield);
		return List.of();
	}
}
